package model

import (
	"gdmin/global"
	"github.com/cloudwego/hertz/pkg/common/hlog"
	"gorm.io/plugin/optimisticlock"
	"gorm.io/plugin/soft_delete"
	"time"
)

type BaseModel struct {
	// 主键
	Id      int                    `gorm:"primaryKey;comment:主键" json:"id"`
	Version optimisticlock.Version `gorm:"comment:乐观锁" json:"-" swaggerignore:"true"`
	// 创建时间
	CreateTime time.Time `gorm:"comment:创建时间;column:create_time;type:datetime(0);autoUpdateTime" json:"createTime"`
	// 更新时间
	UpdateTime time.Time `gorm:"comment:更新时间;column:update_time;type:datetime(0);autoUpdateTime" json:"updateTime"`
	// 创建人id
	CreateUserId int `gorm:"comment:创建人;column:create_user_id;type:bigint(11);create_user_id" json:"createUserId"`
	// 修改人id
	UpdateUserId int `gorm:"comment:更新人;column:update_user_id;type:bigint(11);update_user_id" json:"updateUserId"`
	// 是否删除标记
	IsDel soft_delete.DeletedAt `gorm:"comment:删除标记;softDelete:flag" json:"-" swaggerignore:"true"`
}
type Food struct {
	BaseModel
	Name   string
	Price  float64
	TypeId int
}

// User 用户
type User struct {
	BaseModel
	// 姓名
	Name string `gorm:"comment:姓名" json:"name,omitempty"`
	// 登录名
	LoginName string `gorm:"comment:登录名" json:"loginName,omitempty"`
	// 邮箱
	Email string `gorm:"comment:邮箱" json:"email,omitempty"`
	// 性别
	Sex string `gorm:"comment:性别" json:"sex,omitempty"`
	// 手机号
	Phone string `gorm:"comment:手机号" json:"phone,omitempty"`
	// 密码
	Password string `gorm:"comment:密码" json:"-" json:"-"`
	// 盐
	Slat string `gorm:"comment:盐" json:"-" json:"-"`
}

// Dept 部门
type Dept struct {
	BaseModel
	// 部门名称
	Name string `gorm:"comment:部门名称" json:"name,omitempty" json:"name,omitempty"`
	// 上级id
	Pid      int                `gorm:"comment:上级id" json:"pid,omitempty" json:"pid,omitempty"`
	Children []NodeWithChildren `gorm:"-" json:"children,omitempty"` //此处表示不从数据库中查找此字段
}

// Role 角色
type Role struct {
	BaseModel
	// 角色名称
	Name string `gorm:"comment:角色名称" json:"name,omitempty"`
	// 角色编码
	Code string `gorm:"comment:角色编码" json:"code,omitempty"`
}

// DeptBindUser 部门绑定用户
type DeptBindUser struct {
	BaseModel
	// 用户id
	UserId int `gorm:"comment:用户id" json:"userId,omitempty"`
	// 部门id
	DeptId int `gorm:"comment:部门id" json:"deptId,omitempty"`
	// 是否是主部门
	IsMain bool `gorm:"comment:是否是主部门;default:0" json:"isMain,omitempty"`
}

// RoleBindUser 角色绑定用户
type RoleBindUser struct {
	BaseModel
	// 用户id
	UserId int `gorm:"comment:用户id" json:"userId,omitempty"`
	// 角色id
	RoleId int `gorm:"comment:角色id" json:"roleId,omitempty"`
}

// ResMenu 菜单
type ResMenu struct {
	BaseModel
	// 菜单地址
	Path string `gorm:"comment:菜单地址" json:"path,omitempty"`
	// 菜单名称
	Name string `gorm:"comment:菜单名称" json:"name,omitempty"`
	// 图标
	Icon string `gorm:"comment:图标" json:"iconPic,omitempty"`
	// 上级id
	Pid      int                `gorm:"comment:上级id" json:"pid"`
	Children []NodeWithChildren `gorm:"-" json:"children"`
}

// ResButton 按钮
type ResButton struct {
	BaseModel
	// 唯一编码
	Uid string `gorm:"comment:唯一编码" json:"uid,omitempty"`
	// 名称
	Name string `gorm:"comment:名称" json:"name,omitempty"`
	// 菜单id
	MenuId int `gorm:"comment:菜单id" json:"menuId,omitempty"`
}

// ResApi 接口
type ResApi struct {
	BaseModel
	// 请求方式
	Method string `gorm:"comment:请求方式" json:"method,omitempty"`
	// 请求地址
	Path string `gorm:"comment:请求地址" json:"path,omitempty"`
	// 接口名称
	Name string `gorm:"comment:接口名称" json:"name,omitempty"`
}

// MenuBindApi 菜单绑定接口
type MenuBindApi struct {
	BaseModel
	// 菜单id
	MenuId int `gorm:"comment:菜单id" json:"menuId,omitempty"`
	// 接口id
	ResApiId int `gorm:"comment:接口id" json:"resApiId,omitempty"`
}

type RoleBindMenu struct {
	BaseModel
	// 菜单id
	MenuId int `gorm:"comment:菜单id" json:"menuId,omitempty"`
	// 角色id
	RoleId int `gorm:"comment:角色id" json:"roleId,omitempty"`
}

// Dict 字典
type Dict struct {
	BaseModel
	// 字典名称
	Name string `gorm:"comment:字典名称" json:"name,omitempty"`
	// 字典编码
	Code string `gorm:"comment:字典编码" json:"code,omitempty"`
	// 字典类型
	Type int `gorm:"comment:字典类型" json:"type,omitempty"`
	// 上级id
	Pid      int                `gorm:"comment:上级id" json:"pid,omitempty"`
	Children []NodeWithChildren `gorm:"-" json:"children,omitempty"` //此处表示不从数据库中查找此字段
}

// DictItem 字典项
type DictItem struct {
	BaseModel
	// 字典id
	DictId int `gorm:"comment:字典id" json:"dictId,omitempty"`
	// 字典项名称
	Name string `gorm:"comment:字典项名称" json:"name,omitempty"`
	// 字典项编码
	Code string `gorm:"comment:字典项编码" json:"code,omitempty"`
}

type Log struct {
	BaseModel
	Path        string `gorm:"comment:访问地址" json:"path,omitempty"`
	Method      string `gorm:"comment:请求方式" json:"method,omitempty"`
	Body        string `gorm:"comment:请求参数" json:"body,omitempty"`
	QueryString string `gorm:"comment:请求参数" json:"queryString,omitempty"`
	UserId      int    `gorm:"comment:用户id" json:"userId,omitempty"`
}

func InitDatabase() {
	createTable(&Food{})
	createTable(&User{})
	createTable(&Dept{})
	createTable(&Role{})
	createTable(&DeptBindUser{})
	createTable(&RoleBindUser{})
	createTable(&RoleBindMenu{})
	createTable(&ResMenu{})
	createTable(&ResButton{})
	createTable(&ResApi{})
	createTable(&MenuBindApi{})
	createTable(&Dict{})
	createTable(&Log{})
	createTable(&DictItem{})

}
func (v Log) TableName() string {
	return "log"
}
func (v RoleBindMenu) TableName() string {
	return "role_bind_menu"
}
func (v DictItem) TableName() string {
	return "dict_item"
}
func (v ResMenu) TableName() string {
	return "res_menu"
}
func (v ResButton) TableName() string {
	return "res_button"
}
func (v ResApi) TableName() string {
	return "res_api"
}
func (v MenuBindApi) TableName() string {
	return "menu_bind_api"
}
func (v Dict) TableName() string {
	return "dict"
}

func (v RoleBindUser) TableName() string {
	return "role_bind_user"
}
func (v DeptBindUser) TableName() string {
	return "dept_bind_user"
}
func (v Role) TableName() string {
	return "role"
}
func (v Dept) TableName() string {
	return "dept"
}
func (v User) TableName() string {
	return "user"
}

func (v Food) TableName() string {
	return "food"
}

type NodeWithChildren interface {
	GetID() int
	GetParentID() int
	GetChildren() []NodeWithChildren
	SetChildren(children []NodeWithChildren)
}

func (c *ResMenu) GetID() int {
	return c.Id
}

func (c *ResMenu) GetParentID() int {
	return c.Pid
}

func (c *ResMenu) GetChildren() []NodeWithChildren {
	return c.Children
}

func (c *ResMenu) SetChildren(children []NodeWithChildren) {
	c.Children = children
}

func (c *ResMenu) MakeTree(records []ResMenu) []NodeWithChildren {
	var convertedNodes []NodeWithChildren
	for _, category := range records { //这一步很关键，此处将数据转换为NodeWithChildren
		cat := category
		convertedNodes = append(convertedNodes, &cat)
	}
	return BuildTree(convertedNodes)
}

func (c *Dict) GetID() int {
	return c.Id
}

func (c *Dict) GetParentID() int {
	return c.Pid
}

func (c *Dict) GetChildren() []NodeWithChildren {
	return c.Children
}

func (c *Dict) SetChildren(children []NodeWithChildren) {
	c.Children = children
}

func (c *Dict) MakeTree(records []Dict) []NodeWithChildren {
	var convertedNodes []NodeWithChildren
	for _, category := range records { //这一步很关键，此处将数据转换为NodeWithChildren
		cat := category
		convertedNodes = append(convertedNodes, &cat)
	}
	return BuildTree(convertedNodes)
}

func (c *Dept) GetID() int {
	return c.Id
}

func (c *Dept) GetParentID() int {
	return c.Pid
}

func (c *Dept) GetChildren() []NodeWithChildren {
	return c.Children
}

func (c *Dept) SetChildren(children []NodeWithChildren) {
	c.Children = children
}

func (c *Dept) MakeTree(records []Dept) []NodeWithChildren {
	var convertedNodes []NodeWithChildren
	for _, category := range records { //这一步很关键，此处将数据转换为NodeWithChildren
		cat := category
		convertedNodes = append(convertedNodes, &cat)
	}
	return BuildTree(convertedNodes)
}

func BuildTree(nodes []NodeWithChildren) []NodeWithChildren {
	nodeMap := make(map[int]NodeWithChildren)
	// 将所有节点放入 map 中，以 ID 作为 key
	for _, node := range nodes {
		nodeMap[node.GetID()] = node
	}
	// 遍历节点，根据 ParentID 将子节点连接到对应的父节点上
	var rootNodes []NodeWithChildren
	for _, node := range nodes {
		parentID := node.GetParentID()
		if parentID == 0 || node.GetID() == node.GetParentID() {
			rootNodes = append(rootNodes, node)
		} else {
			parent, ok := nodeMap[parentID]
			if ok {
				children := parent.GetChildren()
				children = append(children, node.(NodeWithChildren))
				parent.SetChildren(children)
			}
		}
	}

	return rootNodes
}

func createTable(dst interface{}) {
	if !global.DB.Migrator().HasTable(dst) {
		err := global.DB.Migrator().AutoMigrate(dst)
		if err != nil {
			hlog.Info("建表失败", dst)

		}
		hlog.Info("建表成功", dst)

	}
}
